package com.iman.locker.service;

import android.annotation.TargetApi;
import android.app.ActivityManager;
import android.app.usage.UsageStats;
import android.app.usage.UsageStatsManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Build;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;

import com.iman.locker.model.AppInfo;
import com.iman.locker.persistence.DbHelper;

import java.util.ArrayList;
import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * 应用启动观测员(注册临听，如果有启动将通知注册者）
 * Created by esirong on 2015-12-04.
 */
public class AppsWatcher {
    private static final String TAG = "AppsWatcher";
    private Context mContext;
    private Handler handler = new Handler();
    private Runnable check;
    private boolean paused = true;
    private String ignoreCheckActiveApp = "";//正在锁定或正在放行的应用名
    protected final ArrayList<OnAppLauncherListener> mAppLauncherListeners = new ArrayList<>();

    public AppsWatcher(Context context) {
        mContext = context;
        start();
    }

    public void start() {
        if (check == null) {
            check = new Runnable() {
                @Override
                public void run() {
                    handler.removeCallbacks(check);
                    handler.postDelayed(check, 500);
                    String activePackage = checkAppLauncher();
                    Log.d(TAG, "检查应用启动:" + activePackage);
                    if (isNeedToLock(activePackage)) {
                        notifyAppLaunched(activePackage);
                    }
                }
            };
        }
        handler.post(check);
        paused = false;
    }

    public void stop() {
        handler.removeCallbacks(check);
        paused = true;
    }

    /**
     * 查看应用的启动情况，如果有需要拦截的应用启动了，将返回它的包名。
     *
     * @return 需要被拦截的应用包名
     */
    private String checkAppLauncher() {
        String result = getRunningApp();
        return result;

    }

    /**
     * 检查传的应用包名是不是需要被拦截(主面面默认不拦截)
     *
     * @param activePackage 应用包名
     * @return 如果是则返加true，如果不是则返回false
     */
    private boolean isNeedToLock(String activePackage) {
        if (TextUtils.isEmpty(activePackage)) {
            return false;
        }
        if (isOwnApp(activePackage)) {
            return false;
        }
        //主页面不拦截
        if (isHome(activePackage)) {
            startWatcherAppLauncher();
            return false;
        }
        //如果当前解锁的，则不需要再拦截
        if (isInWatching(activePackage)) {
            return false;
        } else {
            startWatcherAppLauncher();
        }
        List<AppInfo> appInfoList = DbHelper.getInstance().findAll();
        if (appInfoList == null || appInfoList.isEmpty()) {
            return false;
        }
        for (AppInfo appInfo : appInfoList) {
            if (activePackage.equals(appInfo.packageName)) {
                return true;
            }
        }
        return false;
    }

    public boolean isOwnApp(String packageName) {
        return mContext.getPackageName().contains(packageName);
    }

    //正在被看门狗监视下的应应用
    private boolean isInWatching(String activePackage) {
        return ignoreCheckActiveApp != null && ignoreCheckActiveApp.equals(activePackage);
    }

    private void startWatcherAppLauncher() {
        ignoreCheckActiveApp = "";
    }

    //忽略检查
    public void stopCheckApp(String activePackage) {
        ignoreCheckActiveApp = activePackage;
    }

    /**
     * 判断当前界面是否是桌面
     */
    public boolean isHome(String packageName) {
        return getHomes().contains(packageName);
    }

    /**
     * 获得属于桌面应用的应用包名称
     *
     * @return 返回包含所有包名的字符串列表
     */

    private List<String> getHomes() {
        List<String> names = new ArrayList<>();
        PackageManager packageManager = mContext.getPackageManager();
        Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.addCategory(Intent.CATEGORY_HOME);
        List<ResolveInfo> resolveInfo = packageManager.queryIntentActivities(intent,
                PackageManager.MATCH_DEFAULT_ONLY);
        for (ResolveInfo ri : resolveInfo) {
            names.add(ri.activityInfo.packageName);
        }
        return names;
    }

    /**
     * 获取正在奔跑中的应用
     *
     * @return 正在前台显示应用的包名
     */
    private String getRunningApp() {
        String result;
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT_WATCH) {
            result = getProcessNew();
        } else {
            result = getProcessOld();
        }
        return result;
    }

    //API 21 and above
    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private String getProcessNew() {
        String topPackageName = null;
        UsageStatsManager usage = (UsageStatsManager) mContext.getSystemService(Context.USAGE_STATS_SERVICE);
        long time = System.currentTimeMillis();
        List<UsageStats> stats = usage.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, time - 1000 * 10, time);
        if (stats != null) {
            SortedMap<Long, UsageStats> runningTask = new TreeMap<>();
            for (UsageStats usageStats : stats) {
                runningTask.put(usageStats.getLastTimeUsed(), usageStats);
            }
            if (runningTask.isEmpty()) {
                return null;
            }
            topPackageName = runningTask.get(runningTask.lastKey()).getPackageName();
        }
        return topPackageName;
    }

    //API below 21
    @SuppressWarnings("deprecation")
    private String getProcessOld() {
        String topPackageName = null;
        ActivityManager activity = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningTaskInfo> runningTask = activity.getRunningTasks(1);
        if (runningTask != null) {
            ActivityManager.RunningTaskInfo taskTop = runningTask.get(0);
            ComponentName componentTop = taskTop.topActivity;
            topPackageName = componentTop.getPackageName();
        }
        return topPackageName;
    }

    /**
     * 添加观测者
     *
     * @param listener 观测者
     */
    public void addAppLauncherListener(OnAppLauncherListener listener) {
        synchronized (mAppLauncherListeners) {
            mAppLauncherListeners.add(listener);
        }
    }

    /**
     * 通知观测人
     *
     * @param appPackageName 应用包名
     */
    protected final void notifyAppLaunched(String appPackageName) {
        synchronized (mAppLauncherListeners) {
            for (int i = 0; i < mAppLauncherListeners.size(); i++) {
                mAppLauncherListeners.get(i).onAppLaunched(appPackageName);
            }
        }
    }

    /**
     * 应用启动监听回调接口
     */
    public interface OnAppLauncherListener {
        void onAppLaunched(String appPackageName);
    }
}
